import pygame,sys,random,time
all_block=[    # 物块形状的绘制
      [[0, 0], [0, -1], [0, 1], [0, 2]],
      [[0, 0], [0, 1], [1, 1], [1, 0]],
      [[0, 0], [0, -1], [-1, 0], [-1, 1]],
      [[0, 0], [0, 1], [-1, -1], [-1, 0]],
      [[0, 0], [0, 1], [1, 0], [0, -1]],
      [[0, 0], [1, 0], [-1, 0], [1, -1]],
      [[0, 0], [1, 0], [-1, 0], [1, 1]],
]
# 窗口顶部为 21行 用来存储物块初始位置 不绘制 所以第21行每列为0
background=[[0 for colum in range(0,10)]for row in range(0,22)]  # 绘制窗口的行数和列数
background[0]=[1 for column in range(0,10)]  # 作为最初底部碰撞检测，要将第0列改为第1列
# 全局变量
times=0
score=[0]
gameover=[]
press=False # 按键加快下落速度
select_block=list(random.choice(all_block))  # 从七个形状中随机挑选物块形状
initial_position=[21,5]  # 物块初始位置
pygame.init()
# 窗口大小的绘制
screen=pygame.display.set_mode((250,500))
def block_down():
      # 物块初始位置，即y=21 x=5
      y=initial_position[0]
      x=initial_position[1]
      y-=1 # 物块下落速度
      # 检测当前所选择物块的行列位置
      for row,column in select_block:
            row+=y
            column+=x
            # 如果到达窗口底部跳出for循环，进行下一个环节
            if background[row][column]==1:
                  break
      # 否则更新初始位置
      else:
            initial_position.clear()
            initial_position.extend([y,x])
            return
      y,x = initial_position
      for row,column in select_block:
            # 把物块所停留的位置从0改成1 当位置变成1时显示停靠的物块
            background[y+row][x+column]=1
      complete_row=[] # 完成的行
      # 实现当铺满一行后 删除铺满的一行
      for row in range(1,21):
            if 0 not in background[row]:
                  complete_row.append(row)
      complete_row.sort(reverse=True)
      # 删除1行加1分 将分数设置在窗口标题上
      for row in complete_row:
            background.pop(row)
            background.append([0 for column in range(0,10)])

      score[0]+=len(complete_row)
      pygame.display.set_caption('分数 '+str(score[0])+'')
      # 重置所选择物块的位置 和物块的初始位置
      select_block.clear()
      select_block.extend(list(random.choice(all_block))) # 一个物块的操作结束，随机下一个物块
      initial_position.clear()
      initial_position.extend([20, 5])
      y, x = initial_position
      for row, column in select_block:
            row += y
            column += x
            if background[row][column] == 1: # 是否物块堆叠到窗口顶部
                  gameover.append(1)
      else:
            return
# 绘制窗口动态方块
def draw_block():
      y, x = initial_position
      for row, column in select_block:
            row += y
            column += x
            # colum*25,500-row*25表示一个方块的位置
            pygame.draw.rect(screen, (255, 0, 255), (column * 25, 500 - row * 25, 23, 23))
      # 窗口底部的静态方块的绘制
      for row in range(0, 20):
            for column in range(0, 10):
                  if background[row][column] == 1:
                        pygame.draw.rect(screen, (255, 166, 0), (column * 25, 500 - row * 25, 23, 23))
# 物块的选择
def rotate():
      y,x=initial_position
      # 选择90度方块的每个坐标都改变
      rotating_position=[(-column,row)for row,column in select_block]
      for row,column in rotating_position:
            row+=y
            column+=x
            if column<0 or column>9 or background[row][column]:
                  break
      # 更新位置
      else:
            select_block.clear()
            select_block.extend(rotating_position)
# 物块碰撞检测
def move(n):
      y, x = initial_position
      x+=n
      for row, column in select_block:
            row += y
            column += x
            # 防止物块移出窗口  检测动态和静态的碰撞
            if column < 0 or column > 9 or background[row][column]:
                  break
      # 更新位置
      else:
            initial_position.clear()
            initial_position.extend([y,x])
# 游戏按键处理
while True:
      screen.fill((0,234,255))
      for event in pygame.event.get():
            if event.type==pygame.QUIT:
                  sys.exit()
            elif event.type==pygame.KEYDOWN and event.key==pygame.K_LEFT:
                  move(-1)
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_RIGHT:
                  move(1)
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_UP:
                  rotate()
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_DOWN:
                  press=True
            elif event.type == pygame.KEYUP and event.key == pygame.K_DOWN:
                  press=False
            if event.type==pygame.KEYUP:
                  if event.key == pygame.K_DOWN:
                        press=False
      if press: # 按键时加快物块下落
            times+=10
      if times>=50: # 50为时间间隔
            block_down()
            times=0
      else:
            times+=1 # 默认下落速度
      if gameover:
            sys.exit() # 退出游戏
      draw_block() # 窗口整体重新绘制
      pygame.time.Clock().tick(200) # 控制游戏整体绘制速度
      pygame.display.update() # 屏幕更新